package com.hyxt.DTO;


import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hyxt.dao.RedisServiceDAO;
import com.hyxt.utils.Exeption.ProtocolCheckExeption;
import com.hyxt.utils.T809_Util;
import com.hyxt.utils.bytes.ByteUtil;
import com.hyxt.utils.bytes.BytesUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

public class T809ServerHandler extends ChannelInboundHandlerAdapter {
    /**
     * 客户端ip
     */
    private String ip;
    /**
     * 客户端端口
     */
    private Integer port;
    /**
     * 主从标识
     */
    private Integer mainOrBranch;
    /**
     * 链路缓存
     */
    public final static Map<String,Channel> channelMap = new HashMap<String,Channel>();
    /**
     * 唯一标识
     */
    private Integer sign;
    /**
     * 接收转发标识
     */
    private Integer accessOrForward;
    /**
     * T809拆解包对象
     */
    private T809Case t809Case = new T809Case();
    /**
     * 输入数据缓存
     */
    private ByteBuf in = Unpooled.buffer();
    /**
     * redis接口
     */
    RedisServiceDAO redisServiceDAO;
    public T809ServerHandler(Integer mainOrBranch,RedisServiceDAO redisServiceDAO,Integer accessOrForward){
        this.mainOrBranch = mainOrBranch;
        this.redisServiceDAO = redisServiceDAO;
        this.accessOrForward = accessOrForward;
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //原始数据
        byte[] bytes = (byte[]) msg;
//        byte[] bytesS = BytesUtil.toStringHex("5b0000001f0032a63a10020225510102010f0055d5ae1100000004d2232e5d");
        //数据完整性
        in.writeBytes(bytes);
        byte[] datas =  t809Case.disassemblyByByteBuf(in);
        if(datas==null){
            return;
        }
        //反转义
        byte[] reverseBytes = T809_Util.reverseEscapeData(datas);
        //CRC校验
        // 用校验方法算出的crc校验码
        short checkCode = BytesUtil.parseBytesToShort(T809_Util.check(reverseBytes));
        // 数据体携带的crc校验码
        short crcCode = BytesUtil.parseBytesToShort(BytesUtil.cutBytes(reverseBytes.length - 3, 2, reverseBytes));
        // 判断crc校验码是否正确
        boolean check = checkCode == crcCode;
        if (check){
            if (sign==null){
                byte[] gnsscenteridData = BytesUtil.getDWord(11, reverseBytes);
                // 截取接入码(唯一标识)
                sign = BytesUtil.parseBytesToInt(gnsscenteridData);
                HashMap signMap = new HashMap();
                signMap.put("position","server");
                signMap.put("ip",ip+"-"+port+"-"+mainOrBranch);
                //唯一标识与链路的关系存储到redis
                redisServiceDAO.setMap(sign+mainOrBranch+"",signMap,0);
            }
            //发送到redis通道
            JSONObject json =new JSONObject();
            json.put("ip",ip);
            json.put("port",port);
            json.put("mainOrBranch",mainOrBranch);
            json.put("datas",new String(reverseBytes));
            if(accessOrForward==0){
                redisServiceDAO.sendMessage("T809AccessMessage", JSON.toJSONString(json));
            }else if (accessOrForward==1){
                redisServiceDAO.sendMessage("T809ForwardMessage", JSON.toJSONString(json));
            }

        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //获取ip和端口
        InetSocketAddress ipPort = (InetSocketAddress) ctx.channel().remoteAddress();
        ip = ipPort.getAddress().toString().substring(1);
        port = ipPort.getPort();
        //链路存入缓存中
        channelMap.put(ip+"-"+port+"-"+mainOrBranch,ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //移除链路
        channelMap.remove(ip+"-"+port+"-"+mainOrBranch,ctx.channel());
        //移除redis中的对应关系
        redisServiceDAO.delete(sign+mainOrBranch+"",0);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //移除链路
        channelMap.remove(ip+"-"+port+"-"+mainOrBranch,ctx.channel());
        //移除redis中的对应关系
        redisServiceDAO.delete(sign+mainOrBranch+"",0);
    }
}
